package org.quangnd.musicplayer;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.SeekBar.OnSeekBarChangeListener;

class Mp3Filter implements FilenameFilter {
	@Override
	public boolean accept(File dir, String name) {
		return (name.endsWith(".mp3"));
	}
}

public class MainWindow extends Activity {
	public boolean SHUFFLE = false;
	public int REPEAT = 0; 
	private boolean IS_PAUSED = false;
	private boolean IS_STOP = true;
	private final int INTERVAL = 1000;
		
	/*
	 * Global variables
	 */
	private static final String MEDIA_PATH = new String("/sdcard/music/The Wall");
	private List<String> songs = new ArrayList<String>();
	private MediaPlayer mp = null;
	private Handler handler;
	
	private int currentItem = -1;	
	
	/**
	 * Control variables
	 */
	private ImageButton imgbtn_Previous;
	private ImageButton imgbtn_Next;
	private ImageButton imgbtn_Start;
	private ImageButton imgbtn_Repeat;
	private ImageButton imgbtn_Shuffle;
	private TextView tv_total;
	private TextView tv_progress;
	private TextView tv_song_tittle;
	private TextView tv_song_album;
	private TextView tv_song_artist;
	private TextView tv_song_composer;
	private TextView tv_song_year;
	private SeekBar playingStatus;	
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);        

		// Get control instances
        getControlInstances();
       
        // Set action listeners
        addActionListeners();
        
        // Setup media player
        setupMediaPlayer();
        
        // Get songs from media path
        updateSongList();
    }
    
    /**
     * Get control instances
     */
	private void getControlInstances() {
        imgbtn_Previous = (ImageButton) findViewById(R.id.ImgBtn_Previous);
        imgbtn_Next = (ImageButton) findViewById(R.id.ImgBtn_Next);
        imgbtn_Start = (ImageButton) findViewById(R.id.ImgBtn_Start);
        imgbtn_Repeat = (ImageButton) findViewById(R.id.ImgBtn_Repeat);
        imgbtn_Shuffle = (ImageButton) findViewById(R.id.ImgBtn_Shuffle);        
        playingStatus = (SeekBar) findViewById(R.id.SeekBar_Progress);
        tv_total = (TextView) findViewById(R.id.total_time);
        tv_progress = (TextView) findViewById(R.id.progress_time);
        tv_song_tittle= (TextView) findViewById(R.id.song_tittle);
        tv_song_album= (TextView) findViewById(R.id.song_album);
        tv_song_composer= (TextView) findViewById(R.id.song_composer);
        tv_song_artist= (TextView) findViewById(R.id.song_artist);
        tv_song_year= (TextView) findViewById(R.id.song_year);
	}
    
    /**
     * Add action listener
     */
	private void addActionListeners() {
		imgbtn_Next.setOnClickListener(nextButton_Listener);
        imgbtn_Previous.setOnClickListener(previousButton_Listener);
        imgbtn_Start.setOnClickListener(playButton_Listener);
        imgbtn_Repeat.setOnClickListener(repeatButton_Listener);
        imgbtn_Shuffle.setOnClickListener(shuffleButton_Listener);
        playingStatus.setOnSeekBarChangeListener(playProgress_Listener);
	}
	
	/**
     * Setup media player
     */
	private void setupMediaPlayer() {
		mp = new MediaPlayer();
        mp.setLooping(false);
        handler = new Handler();
        mp.setOnCompletionListener(mediaComplete_Listener);
	}
    
	/**
     * This is use to get the file names from the local path and then update to the list
     */
	private void updateSongList() {
		File home = new File(MEDIA_PATH);
		File[] fileList = home.listFiles(new Mp3Filter());
		if (fileList != null && fileList.length > 0) {
			for (int i = fileList.length - 1; i >= 0; i--) {				
				songs.add(fileList[i].getName());
			}
		}		
	}
	
    /**
     * Create Menu
     */
    @Override
	public boolean onPrepareOptionsMenu(Menu menu) {
    	// Initialize menu
    	super.onPrepareOptionsMenu(menu);
    	menu.clear();
    	    	
    	// Add items to the menu
    	menu.add(0, 0, 0, "Exit");
    	menu.add(0, 1, 1, "Playlist");
    	menu.add(0, 2, 2, "Get Art");
    	menu.add(0, 3, 3, "Preferences");
    	menu.add(0, 4, 4, "Info");
    	menu.add(0, 5, 5, "Help");
    	
    	// Add menu icons
    	(menu.findItem(0)).setIcon(android.R.drawable.ic_delete);
    	(menu.findItem(1)).setIcon(android.R.drawable.ic_menu_agenda);
    	(menu.findItem(2)).setIcon(R.drawable.getart);
    	(menu.findItem(3)).setIcon(android.R.drawable.ic_menu_preferences);    	
    	(menu.findItem(4)).setIcon(android.R.drawable.ic_menu_info_details);    	
    	(menu.findItem(5)).setIcon(android.R.drawable.ic_menu_help);
    	
    	return true;
    }
       
    
    /**
     * Create dialog for display when menu items are clicked
     */
    protected Dialog onCreateDialog(int id) {
    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
    	CharSequence[] items;
    	// For info menu item
    	if (id == 0) {	        
	        String inputInformation = GetMusicInformation();
	        items = inputInformation.split("\n");
	
	        builder.setTitle("Song Information");
	        builder.setItems(items, new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int item) {                
	            }
	        });	        
    	}
    	
    	// For play list menu item
    	else if (id == 1){
    		items = songs.toArray(new String[songs.size()]);
    		builder.setTitle("Playlist");
	        builder.setItems(items, new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int item) {  
	            	// When an item clicked, the music start playing
	            	currentItem = item;
	            	imgbtn_Start.setImageResource(R.drawable.pause);
	        		onStartPlayMusic(item);	
	        		IS_PAUSED = false;	
	            }
	        });	
    	}
    	else {
    		builder.setTitle("About Programme");
    		String intro = "This is Wind Music Player version 1.0";
    		String author = "Developed by: Nguyen Dinh Quang - ndquangr@gmail.com";
    		String other = "For further information, please email to me";
    		builder.setItems(new String[]{intro, author, other}, new DialogInterface.OnClickListener() {
	            public void onClick(DialogInterface dialog, int item) { 
	            	
	            }
	        });	
    	}
    	AlertDialog alert = builder.create();
        return alert;
    }
    
    /**
     * Get song information using content provider
     * @return a string contains all needed information
     */
    private String GetMusicInformation() {
        synchronized (this) {
        	if (currentItem == -1){
        		return "";
        	}
        	String path = "/mnt" +MEDIA_PATH + songs.get(currentItem);
        	
            Cursor mCursor;
            ContentResolver resolver = getContentResolver();
            String where;
            if (path.startsWith("content://media/")) {
                where = null;
            } else {
               where = MediaStore.Audio.Media.DATA + " LIKE \'"+path+"\'";
            }
            
            try {
                mCursor = resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, where, null, null);
                if  (mCursor != null) {
                    if (mCursor.getCount() == 0) {
                        mCursor.close();
                        mCursor = null;
                    } else {
                    	if (mCursor.moveToNext()) {  
                    		String str = "Title: ";
                            int col = mCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);                            
                            if (col > -1){                            	
                            	str += mCursor.getString(col);
                            }
                            
                            str += "\nAlbum: ";
                            col = mCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
                            if (col > -1){                            	
                            	str += mCursor.getString(col);
                            }
                            
                            str += "\nArtist: ";
                            col = mCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
                            if (col > -1){                            	
                            	str += mCursor.getString(col);
                            }
                            
                            str += "\nComposer: ";
                            col = mCursor.getColumnIndex(MediaStore.Audio.Media.COMPOSER);
                            if (col > -1){                            	
                            	str += mCursor.getString(col);
                            }
                            
                            str += "\nYear: ";
                            col = mCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
                            if (col > -1){                            	
                            	str = str + "" + mCursor.getInt(col);
                            }
                            return str;
                    	}
                    }
                }
            } catch (UnsupportedOperationException ex) {
            }       
            return "";
        }
    }   
	
	/**
	 * Start playing a song
	 * @param item: index of the song in the list
	 */
	private void onStartPlayMusic(int item){
		try {	
			// Prepare the media player
			mp.reset();
			mp.setDataSource(MEDIA_PATH + songs.get(item));			
			mp.prepare();
			mp.start();
			
			// Set up the progress bar
			int time = mp.getDuration();
			playingStatus.setMax(time);			
			tv_total.setText(stringForTime(time));
			playingStatus.setProgress(0);
			handler.postDelayed(seekbarTask, INTERVAL);
			
			// Set song information to the labels
			String songInfos = GetMusicInformation();
			String[] items = songInfos.split("\n");
			tv_song_tittle.setText(items[0]);
			tv_song_album.setText(items[1]);
			tv_song_artist.setText(items[2]);
			tv_song_composer.setText(items[3]);
			tv_song_year.setText(items[4]);			
			
		} catch (IOException e) {
			Log.v(getString(R.string.app_name), e.getMessage());
		}
	}
	
	/**
	 * Convert a time value in millisecond to string format
	 * @param time_millisecon: value of the time in millisecond
	 * @return a string represents the time
	 */
	private String stringForTime(int time_millisecon){
		int time_seconds= time_millisecon/1000;
		int seconds = time_seconds%60;
		int minutes = (time_seconds/60)%60;
		int hours = time_seconds/3600;
		if (hours > 0) {
			return (String.format("%d:%02d:%02d", hours, minutes, seconds));
		}
		else {
			return (String.format("%02d:%02d", minutes, seconds));
		}
	}
	
	/**
	 * Updater for the progress bar
	 */
	 public void startPlayProgressUpdater() {
		 playingStatus.setProgress(mp.getCurrentPosition());
	
			if (mp.isPlaying()) {
				Runnable notification = new Runnable() {
			        @Override
					public void run() {
			        	startPlayProgressUpdater();
					}
			    };
			    handler.postDelayed(notification,1000);
	    	}else{
	    		playingStatus.setProgress(0);
	    	}
	    } 

	    
	/************************************************************************
	 * Event Listeners
	 ************************************************************************/
	
	/** Listener for play/pause buttons */
	private OnClickListener playButton_Listener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			if (IS_STOP)
			{
				if (currentItem > -1)
				{					
					onStartPlayMusic(currentItem);
				}
				else {
					currentItem = 0;
					onStartPlayMusic(currentItem);
				}

				IS_STOP = false;
				IS_PAUSED = false;
				imgbtn_Start.setImageResource(R.drawable.pause);
			}
			else
			{
				if (IS_PAUSED)
				{
					mp.start();
					IS_PAUSED = false;
					imgbtn_Start.setImageResource(R.drawable.pause);
				}
				else
				{
					mp.pause();
					IS_PAUSED = true;
					imgbtn_Start.setImageResource(R.drawable.play);
				}
			}
		}			
		
	};
		
	/** Listener for repeat buttons */
	private OnClickListener repeatButton_Listener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			REPEAT ++;
			if (REPEAT > 2) {
				REPEAT = 0;
			}
			
			switch (REPEAT) {
			case 0:
				// Repeat none
				imgbtn_Repeat.setImageResource(R.drawable.repeat_none);
				break;
				
			case 1:
				// Repeat one
				imgbtn_Repeat.setImageResource(R.drawable.repeat_current);
				break;

			case 2:
				// Repeat all
				imgbtn_Repeat.setImageResource(R.drawable.repeat_all);
				break;
				
			default:
				break;
			}
		}
	};
	
	/** Listener for shuffle buttons */
	private OnClickListener shuffleButton_Listener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			if (SHUFFLE) {
				SHUFFLE = false;
				imgbtn_Shuffle.setImageResource(R.drawable.shuffle_none);
			}	
			else {
				SHUFFLE = true;
				imgbtn_Shuffle.setImageResource(R.drawable.shuffle);
			}
		}
	};
	
	/** Listener for next buttons */
    private OnClickListener nextButton_Listener = new OnClickListener() {
        @Override
		public void onClick(View v) {   
        	// Calculate next item based on shuffle status and size of the list
        	int nextItem;
        	if (!SHUFFLE) {	        	
				if (currentItem > -1) {
					nextItem = currentItem + 1;
					if (nextItem >= songs.size()) {
						nextItem = 0;
					}
				} else {
					nextItem = 0;
				}
        	} else {
        		nextItem = (new Random()).nextInt(1000)%(songs.size());
        	}
			currentItem = nextItem;
			
			// Set the media player to play new item
			if (mp.isPlaying()) {
				onStartPlayMusic(nextItem);		
				IS_PAUSED = false;
			}	
			else {
				onStartPlayMusic(nextItem);	
				mp.pause();
				IS_PAUSED = true;
			}
        }
    };
    
    /** Listener for previous buttons */
    private OnClickListener previousButton_Listener = new OnClickListener() {
    	@Override
 		public void onClick(View v) {  
    		// Calculate previous item based on shuffle status and size of the list
	   		int preItem;
	   		if (!SHUFFLE) {
				if (currentItem > -1 ) {
					preItem = currentItem - 1;
					if (preItem < 0) {
						preItem = songs.size() - 1;
					}
				} else {
					preItem = songs.size() - 1;
				}
	   		} else {
	   			preItem = (new Random()).nextInt(1000)%(songs.size());
        	}
			currentItem = preItem;
			
			// Set the media player to play new item
			if (mp.isPlaying()) {
				onStartPlayMusic(preItem);	
				IS_PAUSED = false;
			}	
			else {
				onStartPlayMusic(preItem);	
				mp.pause();
				IS_PAUSED = true;
			}
    	}
	};
    
    /** Listener for media completed event */
    private OnCompletionListener mediaComplete_Listener = new OnCompletionListener(){
		@Override
		public void onCompletion(MediaPlayer mp) {			
			int nextItem;
			boolean stop = false;
			if (REPEAT != 1) {
				if (!SHUFFLE) {
					if (currentItem > -1) {
						nextItem = currentItem + 1;
						
						if (nextItem >= songs.size()) {
							if (REPEAT == 2) {
								nextItem = 0;
							}
							else {
								stop = true;
							}
						}
					} else {
						nextItem = 0;
					}
				} else {
					nextItem = (new Random()).nextInt(1000)%(songs.size());
				}
			}
			else {
				nextItem = currentItem;
			}
			if (!stop) {
				currentItem = nextItem;
				IS_PAUSED = false;
				
				onStartPlayMusic(nextItem);						
			}
			else {
				currentItem = 0;
				onStartPlayMusic(currentItem);
				mp.pause();
				IS_PAUSED = true;
				imgbtn_Start.setImageResource(R.drawable.play);
			}
		} 
	};

	/**
	 * Listener fo seekbar
	 */
	private OnSeekBarChangeListener playProgress_Listener = new OnSeekBarChangeListener() {
		
		@Override
		public void onStopTrackingTouch(SeekBar seekBar) {
			// TODO Auto-generated method stub
			int progress = seekBar.getProgress();
			mp.seekTo(progress);
		}
		
		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void onProgressChanged(SeekBar seekBar, int progress,
				boolean fromUser) {
			
		}
	};
	
	
	/**
	 * When the 'Back' key is press, stop program
	 */
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if ( keyCode == KeyEvent.KEYCODE_BACK) {
			stopMenuSelected();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
	
	/**
     * Menu item selected event listener
     */
    @Override
	public boolean onOptionsItemSelected(MenuItem item) {
    	int itemId = item.getItemId();
    	switch (itemId) {
		case 0:
			// Stop menu item
			stopMenuSelected();
			break;
		
		case 1:
			// Show play list menu item
			showPlaylist();
			break;	
			
		case 2:
			Toast.makeText(this, "Get Art", Toast.LENGTH_SHORT).show();
			break;
			
		case 3:			
			Toast.makeText(this, "Preferences", Toast.LENGTH_SHORT).show();
			break;
		
		case 4:	
			// Show song information menu item
			showSongInfor();
			break;
		
		case 5:			
			AlertDialog alert3 = (AlertDialog)onCreateDialog(2);
	        alert3.show();
			break;

		default:
			break;
		}
    	
    	return true;
    }

    /**
     * Show song information
     */    		
	private void showSongInfor() {
		AlertDialog alert2 = (AlertDialog)onCreateDialog(0);
		alert2.show();
	}

    /**
     * Show playlist
     */
	private void showPlaylist() {
		AlertDialog alert = (AlertDialog)onCreateDialog(1);
		alert.show();
	}

    /**
     * Stop menu selected
     */
	private void stopMenuSelected() {
		if (mp != null) {				
			mp.stop();
			mp.release();	
			mp = null;
		}
		this.finish();
	}
	
	/**
	 * This is used for update seek bar progress and set the current played time in text view 
	 */
	private Runnable seekbarTask = new Runnable(){
		@Override
		public void run() {
			if (mp == null)
			{
				return;
			}
			int position = mp.getCurrentPosition();
			playingStatus.setProgress(position);
			tv_progress.setText(stringForTime(position));
			handler.postDelayed(seekbarTask, INTERVAL);
		}
	};
}
